using System.Collections.Immutable;
using DimensionsHelper.LanguageService.Symbols;
using DimensionsHelper.LanguageService.Syntax;

namespace DimensionsHelper.LanguageService;

/// <summary>
///     A value of NULL is a special marker that indicates that the value is not known.
///     A value of NULL is different from an empty or zero value. The Data Model therefore
///     handles NULL values differently from empty and zero values. The way that the IBM® SPSS®
///     Data Collection Data Model handles NULL generally corresponds to the SQL-92 ANSI standard,
///     although there are one or two important exceptions.
///     In market research data, a NULL value typically indicates that the question was not asked.
///     When a respondent is asked a categorical or open-ended question but for some reason does not answer,
///     the data generally holds an empty categorical value ({}) or an empty string ("") respectively
///     (although some questions have one or more special categories to indicate that the respondent did not answer).
///     This means that for categorical and text data, you can distinguish between a question that was asked but not
///     answered and one that was not asked at all. However, in numeric data you cannot distinguish questions that
///     were asked but not answered from those that were not asked at all, because the Data Model currently stores a
///     NULL value for both.
/// </summary>
public class AnalysisNull : AnalysisExpression
{
    internal AnalysisNull(NullLiteral syntaxNode, AnalysisNode? parent) :
        base(AnalysisBoundKinds.Literal, syntaxNode, parent)
    {
        Syntax = syntaxNode;
        Bind(ValueTypeSymbol.Null);
    }


    public override NullLiteral Syntax { get; }

    public override IEnumerable<AnalysisNode> GetChildren()
    {
        return ImmutableArray<AnalysisNode>.Empty;
    }

    internal override void AddChild(AnalysisNode child)
    {
        throw new NotSupportedException("AnalysisNull cannot have children.");
    }

    public override AnalysisExpression? WithImplicitlyConversion(ValueTypeSymbol targetType)
    {
        // Any | Null
        if (ValueTypeSymbol.IsAnyOrNull(targetType))
        {
            return this;
        }

        // String
        if (ValueTypeSymbol.IsString(targetType))
        {
            return AnalysisNodeFactory.String(NodeConverter.ToString(Syntax), Parent);
        }

        // Long
        if (ValueTypeSymbol.Long == targetType)
        {
            return AnalysisNodeFactory.Integer(NodeConverter.ToInteger(Syntax, 0), Parent);
        }

        // Double
        if (ValueTypeSymbol.Double == targetType)
        {
            return AnalysisNodeFactory.Double(NodeConverter.ToDouble(Syntax, 0), Parent);
        }

        // Boolean
        if (ValueTypeSymbol.Boolean == targetType)
        {
            return AnalysisNodeFactory.Boolean(NodeConverter.ToBoolean(Syntax, false), Parent);
        }

        // Date
        if (ValueTypeSymbol.Date == targetType)
        {
            return AnalysisNodeFactory.Date(Syntax, DateTime.UnixEpoch, Parent);
        }

        // Categorical
        return ValueTypeSymbol.Categorical == targetType
            ? AnalysisNodeFactory.Categorical(NodeConverter.ToCategorical(Syntax), Parent)
            : null;
    }
}


public static partial class AnalysisNodeFactory
{
    /// <summary>
    /// 创建一个空值
    /// </summary>
    /// <param name="syntaxNode">原始语法节点</param>
    /// <param name="parent">父节点</param>
    public static AnalysisNull Null(NullLiteral syntaxNode, AnalysisNode? parent)
    {
        return new AnalysisNull(syntaxNode, parent);
    }
}